import os
from typing import Optional, Dict, Any
from datetime import datetime, timedelta

import bcrypt
import jwt

from dotenv import load_dotenv

load_dotenv()

# JWT配置
SECRET_KEY = os.getenv("SECRET_KEY")

ALGORITHM = os.getenv("ALGORITHM")

ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", 30))


def get_hash_password(password: str, rounds: int = 12, max_length: int = 128) -> str:
    """
    哈希密码（使用 bcrypt）

    Args:
        password: 明文密码
        rounds: 计算成本（越高越安全，但越慢）
        max_length: 密码最大长度（防止DoS长密码攻击）

    Returns:
        哈希后的密码（字符串）

    Raises:
        ValueError: 密码为空或过长
    """
    if not password:
        raise ValueError("密码不能为空")
    if len(password) > max_length:
        raise ValueError(f"密码过长（最大 {max_length} 字符）")

    salt = bcrypt.gensalt(rounds=rounds)
    hashed = bcrypt.hashpw(password.encode("utf-8"), salt)
    return hashed.decode("utf-8")


def verify_password(plain_password: str, hashed_password: str) -> bool:
    """
    验证密码

    Args:
        plain_password: 用户输入的明文密码
        hashed_password: 数据库存储的哈希密码

    Returns:
        bool: 密码是否匹配
    """
    try:
        return bcrypt.checkpw(
            plain_password.encode("utf-8"), hashed_password.encode("utf-8")
        )
    except ValueError:
        return False  # 哈希值无效（如格式错误）


def create_access_token(data: Dict[str, Any]) -> str:
    """
    生成 JWT 访问令牌
    """
    payload = data.copy()

    # 设置过期时间
    expire = datetime.now() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    payload.update({"exp": expire})
    print(f"payload-create: {payload}")

    return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)


def verify_token(token: str):
    """
    验证并解码JWT令牌
    """
    try:
        payload = jwt.decode(
            jwt=token,
            key=SECRET_KEY,
            algorithms=[ALGORITHM],
            options={"verify_exp": True},  # 明确启用过期验证
        )
        return payload
    except jwt.PyJWTError as e:
        print(f"Token验证失败: {e}")  # 实际项目中建议使用logging
        return None
